﻿/*****************************************************************
 * @file   lcd_task.c
 * @brief lcd task implementation
 *****************************************************************
 */

#include "ui.h"
#include "slide_switch.h"
#include "lcd_task.h"
#include "key_task.h"
#include "insert.h"
#include <stdbool.h>
#include <string.h>


// 定义一个结构体来存储数字和对应的电压字符串
typedef struct
{
    int value;
    const char *voltageString;
} AttonMapping;

// 初始化映射表
const AttonMapping mappings[] = {
    {1, "10mV"},
    {2, "20mV"},
    {5, "50mV"},
    {10, "0.1V"},
    {20, "0.2V"},
    {50, "0.5V"},
    {100, "1V  "},
    {200, "2V  "},
    {500, "5V  "}
};


/* 波形窗口 */
Oscill_t window = { 0 };

/* 上边栏 */
UpperSildebar_t upperSildebar = { 0 };

/* 下边栏 */
LowerSildebar_t lowerSildebar = { 0 };


static void _UiInit(void);
static const char *_Atten2Str(uint16_t atten);


/**
 * @brief 处理其他任务发送来的消息 单独一个任务避免消息消费不赢
 */
void MsgToLcdProcTask(void *parameter)
{
    Msg_t msg = { (MsgTopic_e)0 };
    Arr_t oscillDataArr = {
        .pArr = oscillData,
        .len = OSCILL_DATA_LEN,
        .size = sizeof(oscillData[0])
    };

    while(1)
    {
        /* 没有消息则继续 */
        if(!xQueueReceive(msgQueueToLcdHandle, &msg, 0))
        {
            // log("[info] msg queue to Lcd empty\n");
            continue;
        }

        /* 消息处理 */
        switch(msg.msgTopic)
        {
        case MSG_TOPIC_VOLTAGE: /* 电压消息 */
        {
            uint16_t vol = (uint16_t)msg.msgData;

            insert(&oscillDataArr, &vol);
            break;
        }

        case MSG_TOPIC_CPL: /* 耦合消息 */
            taskENTER_CRITICAL();
            if(CPL_GND == msg.msgData)
            {
                strncpy(lowerSildebar.cplMode.text, "GND", sizeof("GND"));
            }
            else if(CPL_AC == msg.msgData)
            {
                strncpy(lowerSildebar.cplMode.text, "AC ", sizeof("AC "));
            }
            else
            {
                strncpy(lowerSildebar.cplMode.text, "DC ", sizeof("DC "));
            }
            taskEXIT_CRITICAL();
            break;

        case MSG_TOPIC_ATTEN: /* 衰减倍数消息 */
        {
            const char *str = "err";
            taskENTER_CRITICAL();
            window.sensiv = msg.msgData * 10;
            taskEXIT_CRITICAL();
            str = _Atten2Str(msg.msgData);
            if(strcmp("err", str) == 0) break;
            taskENTER_CRITICAL();
            strncpy(lowerSildebar.verSensitivity.text, str, strlen(str) + 1);
            taskEXIT_CRITICAL();
            break;
        }

        case MSG_TOPIC_KEY: /* 按键消息 */

            break;
        }
    }
}

/**
 * @brief LCD display task
 * @param pvParameters taske parameter
 */
void LcdTask(void *pvParameters)
{
    log("[info] LcdTask start\n");

    /* UI初始化 */
    _UiInit();

    while(1)
    {
        EventBits_t event = 0;
        event = xEventGroupWaitBits(keyEventGroupHandle,
                                    KEY_EVENT_GROUP_SHORT_PRESS_ALL
                                    | KEY_EVENT_GROUP_LONG_PRESS_ALL,
                                    pdTRUE,
                                    pdFALSE,
                                    0);
        switch(event)
        {
        case KEY_EVENT_GROUP_SHORT_PRESS_4:
            LCD_ShowString(150, 150, 150, 100, 16, "key4 short press");
            break;
        case KEY_EVENT_GROUP_SHORT_PRESS_5:
            LCD_ShowString(150, 150, 150, 100, 16, "key5 short press");
            break;
        case KEY_EVENT_GROUP_SHORT_PRESS_6:
            LCD_ShowString(150, 150, 150, 100, 16, "key6 short press");
            break;
        case KEY_EVENT_GROUP_SHORT_PRESS_7:
            LCD_ShowString(150, 150, 150, 100, 16, "key7 short press");
            break;
        case KEY_EVENT_GROUP_LONG_PRESS_4:
            LCD_ShowString(150, 150, 150, 100, 16, "key4 long press");
            break;
        case KEY_EVENT_GROUP_LONG_PRESS_5:
            LCD_ShowString(150, 150, 150, 100, 16, "key5 long press");
            break;
        case KEY_EVENT_GROUP_LONG_PRESS_6:
            LCD_ShowString(150, 150, 150, 100, 16, "key6 long press");
            break;
        case KEY_EVENT_GROUP_LONG_PRESS_7:
            LCD_ShowString(150, 150, 150, 100, 16, "key7 long press");
            break;
        }

        /* 绘制上边栏 */
        UI_DrawUpperSildebar(&upperSildebar);

        /* 绘制下边栏 */
        UI_DrawLowerSildebar(&lowerSildebar);

        /* 绘制波形窗口 */
        UI_DrawOscilloWindow(&window);
    }
}



/*********************************** 私有函数 ***********************************/

/**
 * @brief 初始化UI
 */
static void _UiInit(void)
{
    /* 波形窗口初始化 */
    window.parent.x = 16;
    window.parent.y = 20;
    window.parent.width = 288;
    window.parent.height = 192;
    window.parent.colorBorder = WHITE;
    window.sizeGrid = 24;
    window.colorGrid = GRAY;
    window.tli.value = window.parent.height / 2;
    window.vpi.value = window.parent.height / 2;
    window.tli.color = GREEN;
    window.vpi.color = GREEN;

    /* 上边栏初始化 */
    upperSildebar.parent.x = 10;
    upperSildebar.parent.y = 0;
    upperSildebar.parent.width = 300;
    upperSildebar.parent.height = 20;

    /* 下边栏初始化 */
    lowerSildebar.parent.x = window.parent.x;
    lowerSildebar.parent.y = window.parent.y + window.parent.height;
    lowerSildebar.parent.width = window.parent.width;
    lowerSildebar.parent.height = lcddev.width - window.parent.y - window.parent.height;

    lowerSildebar.verSensitivity.x = 1;
    lowerSildebar.verSensitivity.y = 10;
    lowerSildebar.verSensitivity.size = FONT_16;
    lowerSildebar.verSensitivity.color = YELLOW;
    lowerSildebar.verSensitivity.text = pvPortMalloc(sizeof(char) * 5);

    lowerSildebar.cplMode.x = 45;
    lowerSildebar.cplMode.y = 10;
    lowerSildebar.cplMode.size = FONT_16;
    lowerSildebar.cplMode.color = YELLOW;
    lowerSildebar.cplMode.text = pvPortMalloc(sizeof(char) * 4);
    memset(lowerSildebar.cplMode.text, 0, sizeof(char) * 4);
}

/**
 * @brief 将衰减倍数转换为对应的电压字符串
 * @param atten 衰减倍数
 */
static const char *_Atten2Str(uint16_t atten)
{
    for(size_t i = 0; i < sizeof(mappings) / sizeof(mappings[0]); i++)
    {
        if(mappings[i].value == atten)
        {
            return mappings[i].voltageString;
        }
    }
    return "err";
}
